package projet_coo;

public class Piece {
	Personnage personnage;
	Famille famille;
	protected Case position;
    protected final Plateau E;
    public final boolean isBlue;
    
    
	public Piece(Plateau E, Case c, boolean isBlue, Personnage p, Famille f,String nom){
		personnage = p;
		famille = f;
		personnage.setVitalite(personnage.getVitalite() + famille.getVitalite());
		// on set la limite une seul fois
		personnage.setLimitevitalite(personnage.getVitalite());
		this.E=E;
		position=c;
		c.setOccupee(true);
		this.isBlue=isBlue;
	}
	//changement de famille et de personnage pour la piece 
	
	public void majPiece(Personnage p, Famille f){personnage = p; famille = f;}
	// Cette m�thode teste si la pi�ce � d�placer est de la couleur 
    // de l'�quipe qui doit jouer
    // puis elle v�rifie que la case destination 
    // ne contient pas une piece de la meme equipe : 
    // on ne mange pas les pieces de sa propre equipe

    protected boolean CondGene(Case c){
	return (E.getTour()==isBlue) && 
	    (c.P==null || c.P.isBlue != isBlue);
    }

    // la fonction recherche si le chemin entre a et b est occupé
    // l'entier unit permet de recuperer si on est dans la premiere ou n ieme evaluation donc on le met a 0 quand on appel la fonction 
    // et au sein de la fonction on le met a 1
    protected boolean rechercheChemin(Case depart , Case arrivee,int distance,int unit){
    	
    	int Hauteur = E.getHauteur()-1;
    	int Largeur = E.getLargeur()-1;
    	if(distance < 0){
    		return false;
    	}
    	if(depart.isOccupee() && unit ==  1){//on ajoute la possibilité de voler
    		return false;
    		
    	}
    	if(depart.x == arrivee.x && depart.y == arrivee.y){
    		return true;
    	}
    	else{
    		boolean b1,b2,b3,b4,b5,b6,b7,b8;
    		b1 = false;b2 = false;b3 = false;b4 = false;b5 = false;b6 = false;b7 = false;b8 = false;
    		if( depart.x < Hauteur && depart.y > 0)
    			b1 = rechercheChemin(E.plateau_jeu[depart.x+1][depart.y-1],arrivee,distance - 1,1);
    		if(depart.x < Hauteur && depart.y <Largeur)
    			b2 =  rechercheChemin(E.plateau_jeu[depart.x+1][depart.y+1],arrivee,distance - 1,1);
    		if(depart.x < Hauteur)
    			b3 = rechercheChemin(E.plateau_jeu[depart.x+1][depart.y],arrivee,distance - 1,1);
    		if(depart.x > 0 && depart.y > 0)
    			b4 = rechercheChemin(E.plateau_jeu[depart.x-1][depart.y-1],arrivee,distance - 1,1);
    		if(depart.x > 0 && depart.y < Largeur)
    			b5 = rechercheChemin(E.plateau_jeu[depart.x-1][depart.y+1],arrivee,distance - 1,1);
    		if(depart.x > 0)
    			b6 = rechercheChemin(E.plateau_jeu[depart.x-1][depart.y],arrivee,distance - 1,1);
    		if(depart.y < Largeur)
    			b7 = rechercheChemin(E.plateau_jeu[depart.x][depart.y+1],arrivee,distance - 1,1);
    		if(depart.y > 0 )
    			b8 = rechercheChemin(E.plateau_jeu[depart.x][depart.y-1],arrivee,distance - 1,1);
    		
    		return b1||b2||b3||b4||b5||b6||b7||b8;
    	}
    }
    
    protected int deplacement(Famille f , Personnage p){return f.getMouvement()+p.getMouvement();}
    // la fonction recherche si le chemin entre a et b est occupé
    //la fonction recherche cible regarde si on la porté et si la case d'arrivée est dans la zone 
    protected boolean coupOk(Case depart , Case arrivee){
    	if(arrivee.P != null && depart.P != null){
    		if(Math.sqrt(Math.pow((depart.x - arrivee.x), 2)+Math.pow((depart.y - arrivee.y), 2))<depart.P.personnage.getPortee()){
    			return true;
    		}
    	}
    	return false;
    }
    //la methode soin ok teste si le soin est valide
    // un soin est valide si l'unité soignante est dans une case adjacente a la case soigné
    // et si le soigneur est de la meme couleur que le soigné 
    protected boolean soinOk(Case c){
    	return (Math.abs(c.x - position.x)==1 ||Math.abs(c.x - position.x)==1) && (this.getSoin()!=0)&& ((this.isBlue && c.P.isBlue)||(!this.isBlue && !c.P.isBlue));
    }
    // la m�thode moveOk teste si le d�placement est valide 
    // prendre en compte les r�gles de d�placement sp�cifique
    protected boolean moveOk(Case c){
    	return rechercheChemin(position,c,deplacement(famille,personnage),0)&& c.P == null;    	
    }
    
    // la m�thode moveTo bouge la pi�ce vers la case destination c si
    // le d�placement est valide
    // puis elle mets � jour la variable tour 
    // afin de permettre � l'autre joueur de jouer
    public boolean calculDegat(Piece p){
    	int a = p.getVitalite();
    	int b = this.getForce();
    	int c = p.getResistance();
    	if(a+c-b < a)
    		p.setVitalite(a+c-b);
    	return a+c-b < 0;
    	
    }
    public void moveTo(Case c){
    int PVmax;
    int PVcourant;
    int soins;
    if((isBlue && E.getTour())||(!isBlue && !E.getTour())){
    	if(coupOk(position,c)&& (this.isBlue != c.P.isBlue)){
    		if(calculDegat(c.P)){
    		c.P = null;
    		}
   		E.changeTour();
    	}
    	else if(moveOk(c)){
    		deletePerso(position);
    		position=c;
    		c.P=this;
    		c.setOccupee(true);
    		c.P.setVitalite(c.P.getVitalite()-c.getnbDegat());
    		if(getVitalite()<0){
    			c.P = null;
    			c.setOccupee(false);
    		}
    		E.changeTour();
    	}
    	else if(soinOk(c)){
    		PVmax = c.P.personnage.getLimitevitalite();
    		PVcourant = c.P.personnage.getVitalite();
    		soins = this.personnage.getSoin();
    		if(PVcourant + soins > PVmax)
    			c.P.setVitalite(PVmax);
    		else{c.P.setVitalite(PVcourant+soins);}
    		
    	}
    }
    
    }
    // la m�thode ToString est utilis�e 
    // pour afficher le nom de la pi�ce dans sa case
    // le nom de la pi�ce �tant sp�cifique, cette m�thode est abstraite

    public String ToString(){
    	return this.personnage.getNom();
    	
    }
	public String getNom(){return personnage.getNom();}
	public int getMouvement(){return personnage.getMouvement()+famille.getMouvement();};
	public int getPortee(){return personnage.getPortee();};
	public int getVitalite(){return personnage.getVitalite();}
	public int getPrecision(){return personnage.getPrecision();}
	public int getSoin() {return personnage.getSoin();}
	public int getForce(){return famille.getForce();};
	public int getResistance(){return famille.getResistance();}
	public void setVitalite(int n){ personnage.setVitalite(n);}
	public void deletePerso(Case position){
		position.P=null;
		position.setOccupee(false);
	}
	
	
}
